;(function(){
	
	var databases={};
	
	function Database(name){
		this.db = databases[name]?databases[name]:databases[name]=window.openDatabase(name,'1','db',1024*1024);
		this.transactions=[];
		this.current_trainsaction=null;
		this.current_sql=null;
	}
		
	Database.prototype={
		constructor:Database,
		transaction:function(onSuccess,onError){
			if(!this.db){
				new Error("Database is not open!");
			}
			this.current_trainsaction={"ok":onSuccess,"ng":onError,sqls:[]};
			this.transactions.push(this.current_trainsaction);
			return this;
		},
		trainsaction_ok:function(fun){
			this.current_trainsaction.ok=fun;
			return this;
		},
		executeSql:function(sql,args,onSuccess,onError){
			if(args==undefined){args=[];}
			this.current_sql={"sql":sql,"args":args,"ok":onSuccess,"ng":onError};
			this.current_trainsaction.sqls.push(this.current_sql);
			return this;
		},
		executeSql_ok:function(fun){
			this.current_sql.ok=fun;
			return this;
		},
		commit:function(onSuccess,onError){
			if(onSuccess){this.current_trainsaction.ok=onSuccess;}
			if(onError){this.current_trainsaction.ng=onError;}
			var self=this;
			var exec_trans_fun,next_trans_fun,ok_trans_fun,ng_trans_fun;
			ok_trans_fun=function(){
				if(self.current_trainsaction.ok){self.current_trainsaction.ok();}
				next_trans_fun();
			};
			ng_trans_fun=function(){
				if(self.current_trainsaction.ng){self.current_trainsaction.ng();}
				next_trans_fun();
			};
			next_trans_fun=function(){
				if(self.transactions.length==0){return;}
				self.current_trainsaction=self.transactions.shift();
				self.db.transaction(exec_trans_fun,ok_trans_fun,ng_trans_fun);
			};
			exec_trans_fun=function(trans_obj){
				var ok_sql_fun,ng_sql_fun,next_sql_fun;
				ok_sql_fun=function(tr,rs){
					if(self.current_sql.ok){slef.current_sql.ok(tr,rs);}
					next_sql_fun();
				};
				ng_sql_fun=function(tr,rs){
					if(self.current_sql.ng){slef.current_sql.ng(tr,rs);}
					next_sql_fun();
				};
				next_sql_fun=function(){
					if(self.current_trainsaction.sqls.length==0)return;
					self.current_sql=self.current_trainsaction.sqls.shift();
					trans_obj.executeSql(self.current_sql.sql,self.current_sql.args,ok_sql_fun,ng_sql_fun);
				};
				next_sql_fun();
			}
			next_trans_fun();
		},
		createTable:function(table_name,fields,ok,ng){
			var a = [];
			for(var i in fields){
				a.push("`"+i+"` "+fields[i]);
			}
			var sql="CREATE TABLE IF NOT EXISTS `"+table_name+"` ("+a.join(",")+");";
			this.executeSql(sql,ok,ng);
			return this;
		},
		createIndex:function(table_name,fields,unique,ok,ng){
			var a = [],b=[];
			for(var i in fields){
				a.push("`"+i+"` "+fields[i]);
				b.push(i);
			}
			if(unique==undefined){unique="UNIQUE";}
			var sql="CREATE "+unique+" INDEX IF NOT EXISTS "+
				table_name+	"_"+b.join("_")+
				" ON `"+table_name+"` ("+a.join(",")+");";
			this.executeSql(sql,ok,ng);
			return this;
		},
		insert:function(table_name,data,ok,ng){
			var k=[],q=[],d=[];
			for(var i in data){
				k.push("`"+i+"`");
				q.push("?");
				d.push(data[i]);
			}
			var sql ="INSERT INTO `"+table_name+"` ("+k.join(",")+") VALUES("+q+")";
			this.executeSql(sql,d,ok,ng);
			return this;
		},
		update:function(table_name,data,where,ok,ng){
			var k=[],v=[],w=[],d=[];
			for(var i in data){
				k.push("`"+i+"`=?");
				d.push(data[i]);
			}
			for(var j in where){
				w.push("`"+j+"`=?");
				d.push(where[j]);
			}
			var sql = "UPDATE `"+table_name+"` "+
				"SET "+k.join(",") +
				"WHERE "+w.join(",");
			this.executeSql(sql,d,ok,ng);
			return this;
		},
		select:function(table_name,where,ok,ng){
			var k=[],v=[];
			for(var i in where){
				if(where[i].indexOf("%")!==-1)
					k.push("`"+i+"` like ?");
				else
					k.push("`"+i+"`=?");
				d.push(where[i]);
			}
			var sql="SELECT * FROM `"+table_name+"` WHERE "+k.join(",");
			this.executeSql(sql,d,ok,ng);
			return this;
		},
		deleteRow:function(table_name,where,ok,ng){
			var k=[],v=[];
			for(var i in where){
				if(where[i].indexOf("%")!==-1)
					k.push("`"+i+"` like ?");
				else
					k.push("`"+i+"`=?");
				d.push(where[i]);
			}
			var sql = "DELETE FROM `"+table_name+"` WHERE "+k.join(",");
			this.executeSql(sql,d,ok,ng);
			return this;
		}
	}
	
	
	window.Crawler=window.Crawler||{};
	Crawler.Database=Database;
})();
